package storage.v1;

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;

import com.onpositive.data.units.Unit;
import com.onpositive.data.units.UnitKind;
import com.onpositive.data.units.Units;
import com.onpositive.knowledge.model.IThing;
import com.onpositive.mediawiki.dataminer.WikiThing;
import com.onpositive.mediawiki.propertyparser.ParsedDocument;
import com.onpositive.mediawiki.propertyparser.PropertyCharacteristic;
import com.onpositive.semantic.model.api.realm.IRealm;
import com.onpositive.units.ParsedDate;
import com.onpositive.units.ParsedDimension;
import com.onpositive.units.ParsedFileList;
import com.onpositive.units.ParsedIdent;
import com.onpositive.units.ParsedLinkArray;
import com.onpositive.units.ParsedProperty;
import com.onpositive.units.ParsedScalar;
import com.onpositive.units.ParsedSection;
import com.onpositive.units.ParsedString;
import com.onpositive.units.ParsedValue;
import com.onpositive.units.ParsedValueSequence;
import com.onpositive.units.TextContent;
import com.onpositive.units.UndefinedParsedValue;

public class ProperyDataExtractor {
	
	private HashMap<String,HashMap<String,Integer>> parserStatsMap  = new HashMap<String, HashMap<String,Integer>>() ;
	private HashMap<String,HashMap<UnitKind,Integer>> unitStatsMap = new HashMap<String, HashMap<UnitKind,Integer>>() ;
	private HashSet<String> serviceProperties = new HashSet<String>();
	
	public void extractProperties ( CategoryStorage storage, int flags )
	{
		parserStatsMap.clear() ;
		unitStatsMap.clear() ;	
		
		IRealm<IThing> documentNames = storage.getRealm( null, null, null ) ;
		for( Object obj  : documentNames )
		{
			if( !( obj instanceof IThing) )
				continue ;
			String documentName = ( (IThing) obj ).getId() ;
			for( ParsedProperty prop : storage.getParsedDocument( documentName ).getProps().values() )
			{
				String propertyName = prop.getName() ;
				
				if( prop.isService() )
					serviceProperties.add( propertyName ) ;
				
				for( ParsedValue pv : prop.getValues() )
					commitStats( propertyName , pv ) ;				
			}						
		}
		
		for( String propertyName : parserStatsMap.keySet() )
		{
			PropertyCharacteristic pChar = extractPropertyCharacteristic(propertyName) ;
			if( pChar == null )
				continue ;

			storage.getCategory().getChracteristicsMap().put( propertyName, pChar ) ;
		}		
	}
	
	public void extractProperties ( ParsedDocument pDoc, LowLevelStorage storage, int flags )
	{
		parserStatsMap.clear() ;
		unitStatsMap.clear() ;	
		
		for( ParsedProperty prop : pDoc.getProps().values() )
		{
			String propertyName = prop.getName() ;
			if( !propertyName.equals("text-content") )
				continue ;
			for( ParsedValue pv : prop.getValues() )
				commitStats( propertyName , pv ) ;	
					
			PropertyCharacteristic pChar = extractPropertyCharacteristic(propertyName) ;
			if( pChar == null )
				continue ;
			
			storage.setProperty( new WikiStorageProperty( pChar, storage ) );									
		}						
	}
	
	private void commitStats(String propertyName, ParsedValue parsedValue )
	{
		String parserId = parsedValue.getId() ;
		HashMap< String,Integer> propertyStatsMap = parserStatsMap.get( propertyName ) ;
		if( propertyStatsMap == null ){
			propertyStatsMap = new HashMap<String, Integer>() ;
			parserStatsMap.put( propertyName, propertyStatsMap ) ;
		}
		Integer count = propertyStatsMap.get( parserId ) ;
		count = ( count != null ) ? count+1 : 1 ;
		propertyStatsMap.put( parserId, count ) ;
		
		if( parsedValue instanceof ParsedDimension )
		{			
			try{
				Unit unit = ((ParsedDimension)parsedValue).getUnit();
				if( unit.getKind().equals( UnitKind.UNDEF) )
					return ;
					
				UnitKind unitKind = unit.getPrimaryUnit().getKind() ;
				HashMap<UnitKind,Integer>_propertyStatsMap = unitStatsMap.get( propertyName ) ;
				if( _propertyStatsMap == null ){
					_propertyStatsMap = new HashMap<UnitKind,Integer>() ;
					unitStatsMap.put( propertyName, _propertyStatsMap ) ;
				}
				count = _propertyStatsMap.get( unitKind ) ;
				count = ( count != null ) ? count+1 : 1 ;
				_propertyStatsMap.put( unitKind, count ) ;
			}catch ( NullPointerException e) {
				e.printStackTrace();
			}catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	private static LinkedHashMap<String, Integer> valueRankMap ;
	static{		
		valueRankMap = new LinkedHashMap<String, Integer>() ;
		valueRankMap.put( TextContent.ID, 100500 ) ;
		
		valueRankMap.put( ParsedDate.ID, 10000 ) ;		
		valueRankMap.put( ParsedDimension.ID, 9000 ) ;		
		valueRankMap.put( ParsedScalar.ID, 8000 ) ;
		valueRankMap.put( ParsedValueSequence.ID, 100 ) ;
		valueRankMap.put( ParsedIdent.ID, 40 ) ;
		valueRankMap.put( ParsedString.ID, 30 ) ;
		
		
		valueRankMap.put( ParsedSection.ID, -1   ) ;
		valueRankMap.put( ParsedLinkArray.ID, -9000   ) ;
		valueRankMap.put( ParsedFileList.ID,  -100500 ) ;
		valueRankMap.put( UndefinedParsedValue.ID, -90909090 ) ;
	}
	
	private PropertyCharacteristic extractPropertyCharacteristic( String propertyName ){
		
		HashMap<String,Integer> propertyStats = parserStatsMap.get( propertyName ) ;
		
		if( propertyStats == null )
			return null ;
		
		PropertyCharacteristic pChar = new PropertyCharacteristic() ;
		
		if( serviceProperties.contains(propertyName) )
			pChar.setCharacteristic( PropertyCharacteristic.CHAR_IS_SERVICE_PROPERTY, "true" ) ;
		else
			pChar.setCharacteristic( PropertyCharacteristic.CHAR_IS_SERVICE_PROPERTY, "false" ) ;

		String newParserId = UndefinedParsedValue.ID ;
		Integer newSamplesCount = 0 ;
		for( Integer a : propertyStats.values() )
		{
			if( a == null )
				continue ;			
			newSamplesCount += a ;
		}
		
		double maxCount_Pars = 0 ;
		
		for( Map.Entry<String, Integer> entryLoc : propertyStats.entrySet() )
		{
			String key = entryLoc.getKey() ;
			int a = entryLoc.getValue() ;
			double ratio = ((double)a)/newSamplesCount ;
			
			if( ratio < 0.0500001 )
				continue ;
			
			if( valueRankMap.get(key) > valueRankMap.get(newParserId) ){//a > maxCount_Pars && !key.equals("undef") ){
				maxCount_Pars = a ;
				newParserId = key ;
			}							
		}
		
		Double newRate = maxCount_Pars/newSamplesCount ;
		
		pChar.setCharacteristic( PropertyCharacteristic.CHAR_PROPERTY_NAME_LABEL, propertyName ) ;
		pChar.setCharacteristic( PropertyCharacteristic.CHAR_RATE_LABEL, newRate.toString() ) ;
		pChar.setCharacteristic( PropertyCharacteristic.CHAR_SAMPLES_COUNT_LABEL, newSamplesCount.toString() ) ;
		
		pChar.setCharacteristic( PropertyCharacteristic.CHAR_PARSER_ID_LABEL, newParserId ) ;
		
		if( newParserId.equals( ParsedDimension.ID ) )
		{
			HashMap<UnitKind,Integer> propertyUnitStats = unitStatsMap.get( propertyName ) ;
			if( propertyUnitStats == null )
				return null;
				
			UnitKind newUnit = null;
			double maxCount_Unit = 0 ;
			for( Map.Entry<UnitKind, Integer> entryLoc : propertyUnitStats.entrySet() )
			{
				UnitKind key = entryLoc.getKey() ;
				int a = entryLoc.getValue() ;
				newSamplesCount += a ;
				if( a > maxCount_Unit  ){
					maxCount_Unit = a ;
					newUnit = key ;
				}							
			}
			if( newUnit != null ){
				pChar.setCharacteristic( PropertyCharacteristic.CHAR_UNIT_LABEL, Units.getPrimaryUnit(newUnit).getShortName() ) ;
				pChar.setCharacteristic( PropertyCharacteristic.CHAR_UNIT_KIND_LABEL, newUnit.name() ) ;
			}
		}		
		return pChar ;		
	}

}
